﻿#include "blua.h"

static pblua_t _bl_allocstate( blua_alloc pfn_alloc, void* p_param );
static int _bl_freestate( pblua_t p_lua );
static void* _bl_defaultalloc( void* ud, void* ptr, size_t osize, size_t nsize );
static int _bl_dispatcher( lua_State* p_state );
static int _bl_dump( FILE* p_file, pblua_t p_lua );
static int _bl_dumpstack( FILE* p_file, pblua_t p_lua );

static int _bl_loadfile( pblua_t p_lua, const char* psz_file );
static int _bl_loadstring( pblua_t p_lua, const char* psz_str );
static int _bl_dofile( pblua_t p_lua, const char* psz_file );
static int _bl_dostring( pblua_t p_lua, const char* psz_str );
static int _bl_checkstack( pblua_t p_lua, int n_extra );
static int _bl_call( pblua_t p_lua, int n_arg, int n_result );

static int _bl_pop( pblua_t p_lua, int n_cnt );
static int _bl_insert( pblua_t p_lua, int n_index );
static int _bl_pushnil( pblua_t p_lua );
static int _bl_pushint( pblua_t p_lua, int n_value );
static int _bl_pushstring( pblua_t p_lua, const char* psz_value );
static int _bl_pushlightpointer( pblua_t p_lua, void* p_pointer );
static int _bl_pushtable( pblua_t p_lua );
static int _bl_pushcclosure( pblua_t p_lua, lua_cfunc pfn_func, int n_upvcnt);
static int _bl_pushvalue( pblua_t p_lua, int n_index );

static int _bl_gettable( pblua_t p_lua, int n_index );
static int _bl_settable( pblua_t p_lua, int n_index );
static int _bl_enumtable( pblua_t p_lua, int n_index, blua_cfunc pfn_onenum );

static int _bl_isnumber( pblua_t p_lua, int n_index );
static int _bl_isstring( pblua_t p_lua, int n_index );
static int _bl_isboolean( pblua_t p_lua, int n_index );
static int _bl_isfunction( pblua_t p_lua, int n_index );
static int _bl_iscfunction( pblua_t p_lua, int n_index );
static int _bl_islightuserdata( pblua_t p_lua, int n_index );
static int _bl_isuserdata( pblua_t p_lua, int n_index );
static int _bl_istable( pblua_t p_lua, int n_index );
static int _bl_isthread( pblua_t p_lua, int n_index );
static int _bl_isnil( pblua_t p_lua, int n_index );
static int _bl_isnone( pblua_t p_lua, int n_index );
static int _bl_isnoneornil( pblua_t p_lua, int n_index );

static int _bl_toint( pblua_t p_lua, int n_index, int* pn_value );
static int _bl_tostr( pblua_t p_lua, int n_index, char* psz_buffer, size_t* pn_len );
static int _bl_tobool( pblua_t p_lua, int n_index, int* pn_value );
static int _bl_tocfunc( pblua_t p_lua, int n_index, lua_cfunc* ppfn_value );
static int _bl_topointer( pblua_t p_lua, int n_index, blua_pointer* pp_value );
static int _bl_tonumber( pblua_t p_lua, int n_index, blua_number* pd_value );
static int _bl_touserdata( pblua_t p_lua, int n_index, void** pp_value );

static int _bl_backupstack( pblua_t p_lua, int* pn_top );
static int _bl_recoverystack( pblua_t p_lua, int n_top );
static int _bl_getfieldbyname( pblua_t p_lua, const char* pszu8_fieldname );
static int _bl_setfieldbyname( pblua_t p_lua, const char* pszu8_fieldname, int* pn_tableindex );

static int _bl_exportlib( pblua_t p_lua, const char* pszu8_tablename, pluareg_t p_regs, int n_upvcnt );
static int _bl_exportblib( pblua_t p_lua, const char* pszu8_tablename, pbluareg_t p_regs, int n_upvcnt );

static int _bl_transindex( pblua_t p_lua, int n_index );

pblua_t bl_allocstate( void* p_param )
{
	pblua_t p_lua = NULL;

	bb_error( p_lua = _bl_allocstate( &_bl_defaultalloc, p_param ) );

	bb_exit
	return p_lua;
}

pblua_t bl_allocstate_ex( blua_alloc pfn_alloc, void* p_param )
{
	pblua_t p_lua = NULL;

	bb_error( pfn_alloc && "null alloc function" );
	bb_error( p_lua = _bl_allocstate( pfn_alloc, p_param ) );

	bb_exit
	return p_lua;
}

int bl_freestate( pblua_t p_lua )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_freestate( p_lua ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

pblua_t bl_getblua( lua_State* p_state )
{
	pblua_t p_lua = NULL;

	bb_error( p_state );
	lua_getallocf( p_state, (void**)&p_lua );

	bb_exit
	return p_lua;
}

int bl_loadfile( pblua_t p_lua, const char* psz_file )
{
	int b_ret = 0;

	bb_error( p_lua && psz_file );
	bb_error( _bl_loadfile( p_lua, psz_file ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}
int bl_loadstring( pblua_t p_lua, const char* psz_str )
{
	int b_ret = 0;

	bb_error( p_lua && psz_str );
	bb_error( _bl_loadstring( p_lua, psz_str ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_dofile( pblua_t p_lua, const char* psz_file )
{
	int b_ret = 0;

	bb_error( p_lua && psz_file );
	bb_error( _bl_dofile( p_lua, psz_file ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_dostring( pblua_t p_lua, const char* psz_str )
{
	int b_ret = 0;

	bb_error( p_lua && psz_str );
	bb_error( _bl_dostring( p_lua, psz_str ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_checkstack( pblua_t p_lua, int n_extra )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_checkstack( p_lua, n_extra ) );
	
	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_call( pblua_t p_lua, int n_arg, int n_result )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_call( p_lua, n_arg, n_result ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_dump( FILE* p_file, pblua_t p_lua )
{
	int b_ret = 0;

	bb_error( p_file && p_lua );
	bb_error( _bl_dump( p_file, p_lua ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_dumpstack( FILE* p_file, pblua_t p_lua )
{
	int b_ret = 0;

	bb_error( p_file && p_lua );
	bb_error( _bl_dumpstack( p_file, p_lua ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_insert( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_insert( p_lua, n_index ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pop( pblua_t p_lua, int n_cnt )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_pop( p_lua, n_cnt ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushnil( pblua_t p_lua )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_pushnil( p_lua ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushint( pblua_t p_lua, int n_value )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_pushint( p_lua, n_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}
int bl_pushstring( pblua_t p_lua, const char* psz_value )
{
	int b_ret = 0;
	
	bb_error( p_lua && psz_value );
	bb_error( _bl_pushstring( p_lua, psz_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushlightpointer( pblua_t p_lua, void* p_pointer )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_pushlightpointer( p_lua, p_pointer ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushtable( pblua_t p_lua )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_pushtable( p_lua ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushvalue( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_pushvalue( p_lua, n_index ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushfunction( pblua_t p_lua, lua_CFunction pfn_func )
{
	int b_ret = 0;

	bb_error( p_lua && pfn_func );
	bb_error( _bl_pushcclosure( p_lua, pfn_func, 0 ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_pushcclosure( pblua_t p_lua, lua_CFunction pfn_func, int n_upvcnt )
{
	int b_ret = 0;

	bb_error( p_lua && pfn_func && n_upvcnt >= 0 );
	bb_error( _bl_pushcclosure( p_lua, pfn_func, n_upvcnt ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_isnumber( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isnumber( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isstring( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isstring( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isboolean( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isboolean( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isfunction( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isfunction( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_iscfunction( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_iscfunction( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_islightuserdata( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_islightuserdata( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isuserdata( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isuserdata( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_istable( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_istable( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isthread( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isthread( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isnil( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isnil( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isnone( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isnone( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_isnoneornil( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	b_ret = _bl_isnoneornil( p_lua, n_index );

	bb_exit
	return b_ret;
}

int bl_toint( pblua_t p_lua, int n_index, int* pn_value )
{
	int b_ret = 0;

	bb_error( p_lua && pn_value );
	bb_error( _bl_toint( p_lua, n_index, pn_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_tostr( pblua_t p_lua, int n_index, char* psz_buffer, size_t* pn_len )
{
	int b_ret = 0;

	bb_error( p_lua && pn_len );
	bb_error( _bl_tostr( p_lua, n_index, psz_buffer, pn_len ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_tobool( pblua_t p_lua, int n_index, int* pn_value )
{
	int b_ret = 0;

	bb_error( p_lua && pn_value );
	bb_error( _bl_tobool( p_lua, n_index, pn_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_tocfunc( pblua_t p_lua, int n_index, lua_cfunc* ppfn_value )
{
	int b_ret = 0;

	bb_error( p_lua && ppfn_value );
	bb_error( _bl_tocfunc( p_lua, n_index, ppfn_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_topointer( pblua_t p_lua, int n_index, blua_pointer* pp_value )
{
	int b_ret = 0;

	bb_error( p_lua && pp_value );
	bb_error( _bl_topointer( p_lua, n_index, pp_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;

}
int bl_tonumber( pblua_t p_lua, int n_index, blua_number* pd_value )
{

	int b_ret = 0;

	bb_error( p_lua && pd_value );
	bb_error( _bl_tonumber( p_lua, n_index, pd_value ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}
int bl_touserdata( pblua_t p_lua, int n_index, void** pp_value )
{
	int b_ret = 0;

	bb_error( p_lua && pp_value);
	bb_error( _bl_touserdata( p_lua, n_index, pp_value) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_gettable( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_gettable( p_lua, n_index ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}
int bl_settable( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_settable( p_lua, n_index ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_enumtable( pblua_t p_lua, int n_index, blua_cfunc pfn_onenum )
{
	int b_ret = 0;

	bb_error( p_lua && pfn_onenum );
	bb_error( _bl_enumtable( p_lua, n_index, pfn_onenum ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_backupstack( pblua_t p_lua, int* pn_top )
{
	int b_ret = 0;

	bb_error( p_lua && pn_top );
	bb_error( _bl_backupstack( p_lua, pn_top ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_recoverystack( pblua_t p_lua, int n_top )
{
	int b_ret = 0;

	bb_error( p_lua );
	bb_error( _bl_recoverystack( p_lua, n_top ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_getintbyname( pblua_t p_lua, const char* pszu8_fieldname, int* pn_value )
{
	int b_ret = 0;
	int n_otop = 0;

	bb_error( p_lua && pszu8_fieldname && pn_value );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_getfieldbyname( p_lua, pszu8_fieldname ) );
	bb_error( _bl_toint( p_lua, -1, pn_value ) );
	bb_error( _bl_pop( p_lua, 1 ) );

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

int bl_getstringbyname( pblua_t p_lua, const char* pszu8_fieldname, char* psz_buffer, size_t* pun_len )
{
	int b_ret = 0;
	int n_otop = 0;

	bb_error( p_lua && pszu8_fieldname && psz_buffer && pun_len );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_getfieldbyname( p_lua, pszu8_fieldname ) );
	bb_error( _bl_tostr( p_lua, -1, psz_buffer, pun_len ) );

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

int bl_getfieldbyname( pblua_t p_lua, const char* pszu8_fieldname )
{
	int b_ret = 0;

	bb_error( p_lua && pszu8_fieldname );
	bb_error( _bl_getfieldbyname( p_lua, pszu8_fieldname ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_setintbyname( pblua_t p_lua, const char* pszu8_fieldname, int n_value )
{
	int b_ret = 0;
	int n_tableindex = 0;
	int n_otop = 0;

	bb_error( p_lua && pszu8_fieldname );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_fieldname, &n_tableindex ) );
	bb_error( _bl_pushint( p_lua, n_value ) );
	bb_error( _bl_settable( p_lua, n_tableindex ) );

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

int bl_setstringbyname( pblua_t p_lua, const char* pszu8_fieldname, const char* psz_buffer )
{
	int b_ret = 0;
	int n_tableindex = 0;
	int n_otop = 0;

	bb_error( p_lua && pszu8_fieldname && psz_buffer );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_fieldname, &n_tableindex ) );
	bb_error( _bl_pushstring( p_lua, psz_buffer ) );
	bb_error( _bl_settable( p_lua, n_tableindex ) );

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

int bl_setcclosurebyname( pblua_t p_lua, const char* pszu8_fieldname, lua_CFunction pfn_func, int n_upvcnt )
{
	int b_ret = 0;
	int n_tableindex = 0;
	int n_otop = 0;
	int i = 0;

	bb_error( p_lua && pszu8_fieldname && pfn_func && n_upvcnt >= 0 && n_upvcnt < 255 );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_fieldname, &n_tableindex ) );
	for ( i = 0; i < n_upvcnt; i++ )
	{
		bb_error( _bl_pushnil( p_lua ) );
	}
	bb_error( _bl_pushcclosure( p_lua, pfn_func, n_upvcnt ) );
	bb_error( _bl_settable( p_lua, n_tableindex ) );

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

int bl_setfuncbyname( pblua_t p_lua, const char* pszu8_fieldname, lua_CFunction pfn_func )
{
	return bl_setcclosurebyname( p_lua, pszu8_fieldname, pfn_func, 0 );
}

int bl_setbcclosurebyname( pblua_t p_lua, const char* pszu8_fieldname, blua_cfunc pfn_bfunc, int n_upvcnt )
{
	int b_ret = 0;
	int n_tableindex = 0;
	int n_otop = 0;
	int i = 0;

	bb_error( p_lua && pszu8_fieldname && pfn_bfunc && n_upvcnt >= 0 && n_upvcnt < 254 );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_fieldname, &n_tableindex ) );
	bb_error( _bl_pushlightpointer( p_lua, (void*)pfn_bfunc ) );
	for ( i = 0; i < n_upvcnt; i++ )
	{
		bb_error( _bl_pushnil( p_lua ) );
	}
	bb_error( _bl_pushcclosure( p_lua, &_bl_dispatcher, n_upvcnt + 1 ) );
	bb_error( _bl_settable( p_lua, n_tableindex ) );

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}
int bl_setbfuncbyname( pblua_t p_lua, const char* pszu8_fieldname, blua_cfunc pfn_bfunc )
{
	return bl_setbcclosurebyname( p_lua, pszu8_fieldname, pfn_bfunc, 0 );
}

int bl_setfieldbyname( pblua_t p_lua, const char* pszu8_fieldname, int* pn_tableindex )
{
	int b_ret = 0;

	bb_error( p_lua && pszu8_fieldname && pn_tableindex );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_fieldname, pn_tableindex ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_exportlib( pblua_t p_lua, const char* pszu8_tablename, pluareg_t p_regs, int n_upvcnt )
{
	int b_ret = 0;

	bb_error( p_lua && pszu8_tablename && p_regs && n_upvcnt >= 0 && n_upvcnt < 255 );
	bb_error( _bl_exportlib( p_lua, pszu8_tablename, p_regs, n_upvcnt ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

int bl_exportblib( pblua_t p_lua, const char* pszu8_tablename, pbluareg_t p_regs, int n_upvcnt )
{
	int b_ret = 0;

	bb_error( p_lua && pszu8_tablename && p_regs && n_upvcnt >= 0 && n_upvcnt < 254 );
	bb_error( _bl_exportblib( p_lua, pszu8_tablename, p_regs, n_upvcnt ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

/**************** static function ***********************/

static void* _bl_defaultalloc( void* p_ud, void* p_ptr, size_t un_osize, size_t un_nsize )
{
	void* p_ret = NULL;
	pblua_t p_lua = NULL;

	//bb_assert( p_lua = (pblua_t)p_ud ); oh fuck
	p_lua = (pblua_t)p_ud;
	bb_assert( p_lua );

	if (un_nsize == 0)
	{
		free(p_ptr);
		if ( p_lua->un_totalmem >= un_osize )
			p_lua->un_totalmem -= un_osize;
		else
			p_lua->un_totalmem = 0;
	}
	else
	{
		size_t un_totalmem = p_lua->un_totalmem;
		if ( un_nsize >= un_osize )
		{
			un_totalmem += ( un_nsize - un_osize );
		}
		else
		{
			un_totalmem -= ( un_osize - un_nsize );
		}
		if ( un_totalmem <= p_lua->un_maxmem )
		{
			p_ret = realloc( p_ptr, un_nsize );
			if ( p_ret )
			{
				p_lua->un_totalmem = un_totalmem;
			}
		}
	}
	return p_ret;
}

static pblua_t _bl_allocstate( blua_alloc pfn_alloc, void* p_param )
{
	int b_ret = 0;
	pblua_t p_lua = NULL;

	bb_assert( pfn_alloc );
	bb_error( p_lua = (pblua_t)calloc( 1, sizeof(blua_t) ) ); //bb_error( p_lua = (pblua_t)calloc( 1, sizeof(pblua_t) ) ); fuck!!! 
	p_lua->p_stateparam = p_param;
	p_lua->un_maxmem = BLD_MAX_MEMORY;
	p_lua->un_totalmem = 0;
	bb_error( p_lua->p_state = lua_newstate( (lua_Alloc)pfn_alloc, p_lua ) );	

	b_ret = 1;
	bb_exit
	if ( !b_ret )
	{
		bb_release( p_lua, _bl_freestate );
	}
	return p_lua;	
}

static int _bl_freestate( pblua_t p_lua )
{
	int b_ret = 0;

	bb_assert( p_lua );
	bb_release( p_lua->p_state, lua_close );
	bb_release( p_lua, free );

	b_ret = 1;
	return b_ret;
}

static int _bl_dump( FILE* p_file, pblua_t p_lua )
{
	int b_ret = 0;

	bb_assert( p_file && p_lua );
	fprintf( p_file, "maxx memory:%d\n", p_lua->un_maxmem );
	fprintf( p_file, "used memory:%d\n", p_lua->un_totalmem );

	b_ret = 1;
	return b_ret;
}

static int _bl_dumpstack( FILE* p_file, pblua_t p_lua )
{
	int b_ret = 0;
	int n_top = 0;
	int n_type = 0;
	int i = 0;

	bb_assert( p_file && p_lua && p_lua->p_state );

	n_top = lua_gettop( p_lua->p_state );

	fprintf( p_file, "----------lua stack dump----------\n" );
	fprintf( p_file, "stack count:%d\n", n_top );
	for ( i = 1; i <= n_top; i++ )
	{
		n_type = lua_type( p_lua->p_state, i );
		switch( n_type )
		{
		case LUA_TSTRING:
			{
				fprintf( p_file, "<%d>[%s]:%s\n", i, lua_typename( p_lua->p_state, n_type ), lua_tostring( p_lua->p_state, i) );
				break;
			}
		case LUA_TNUMBER:
			{
				fprintf( p_file, "<%d>[%s]:%g\n", i, lua_typename( p_lua->p_state, n_type ), lua_tonumber( p_lua->p_state, i) );
				break;
			}
		case LUA_TTABLE:
		case LUA_TUSERDATA:
		case LUA_TFUNCTION:
		case LUA_TTHREAD:
			{
				fprintf( p_file, "<%d>[%s]:%p\n", i, lua_typename(p_lua->p_state, n_type ), lua_topointer( p_lua->p_state, i ) );
				break;
			}
		default:
			{
				fprintf( p_file, "<%d>[%s]:unknown\n", i, lua_typename( p_lua->p_state, n_type ) );
			}
		}
	}

	b_ret = 1;
	return b_ret;
}

static int _bl_loadfile( pblua_t p_lua, const char* psz_file )
{
	int b_ret = 0;
	int b_res = 0;

	bb_assert( p_lua && p_lua->p_state && psz_file );
	b_res = luaL_loadfile( p_lua->p_state, psz_file );
	if ( b_res )
	{
		bb_error( 0 && "luaL_loadfile error" );
	}

	b_ret = 1;
	bb_exit
	return b_ret;
}
static int _bl_loadstring( pblua_t p_lua, const char* psz_str )
{
	int b_ret = 0;
	int b_res = 0;

	bb_assert( p_lua && p_lua->p_state && psz_str );
	b_res = luaL_loadstring( p_lua->p_state, psz_str );
	if ( b_res )
	{
		bb_error( 0 && "luaL_loadstring error" );
	}

	b_ret = 1;
	bb_exit
	return b_ret;
}
static int _bl_dofile( pblua_t p_lua, const char* psz_file )
{
	int b_ret = 0;
	int b_res = 0;

	bb_assert( p_lua && p_lua->p_state && psz_file );
	b_res = luaL_dofile( p_lua->p_state, psz_file );
	if ( b_res )
	{
		bb_error( 0 && "luaL_dofile error" );
	}

	b_ret = 1;
	bb_exit
	return b_ret;
}
static int _bl_dostring( pblua_t p_lua, const char* psz_str )
{
	int b_ret = 0;
	int b_res = 0;

	bb_assert( p_lua && p_lua->p_state && psz_str );
	b_res = luaL_dostring( p_lua->p_state, psz_str );
	if ( b_res )
	{
		bb_error( 0 && "luaL_dostring error" )
	}

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_checkstack( pblua_t p_lua, int n_extra )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	n_extra = n_extra >= 0 ? n_extra : 0;
	bb_error( lua_checkstack( p_lua->p_state, n_extra ) );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_call( pblua_t p_lua, int n_arg, int n_result )
{
	int b_ret = 0;
	int n_otop = 0;
	int n_funcindex = 0;

	bb_assert( p_lua && p_lua->p_state && n_arg >= 0 && n_result >= 0 );
	n_otop = lua_gettop( p_lua->p_state );

	bb_error( _bl_checkstack( p_lua, n_result - n_arg - 1 ) );
	bb_error( n_otop > n_arg );
	bb_error( -1 != ( n_funcindex = _bl_transindex( p_lua, -( n_arg + 1 ) ) ) );
	bb_error( _bl_isfunction( p_lua, n_funcindex ) );
	lua_call( p_lua->p_state, n_arg, n_result );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_gettable( pblua_t p_lua, int n_index )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );

	bb_error( _bl_istable( p_lua, n_index ) && "_bl_gettable error:is not table" );

	n_otop = lua_gettop( p_lua->p_state );
	bb_error( n_otop >=1 && "lua_gettable error:invalid param" );
	lua_gettable( p_lua->p_state, n_index );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_otop == n_ntop && "lua_gettable error:stack exception" );

	b_ret = 1;
	bb_exit
	return b_ret;
}
static int _bl_settable( pblua_t p_lua, int n_index )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( _bl_istable( p_lua, n_index ) && "_bl_settable error:is not table" );

	n_otop = lua_gettop( p_lua->p_state );
	bb_error( n_otop >= 2 && "lua_settable error:invalid param" );
	lua_settable( p_lua->p_state, n_index );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop - 2 && "lua_settable error:stack exception" );
	
	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_enumtable( pblua_t p_lua, int n_index, blua_cfunc pfn_onenum )
{
	int b_ret = 0;
	int n_otop = 0, n_etop = 0;

	bb_assert( p_lua && p_lua->p_state && pfn_onenum );
	n_index = _bl_transindex( p_lua, n_index );
	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_istable( p_lua, n_index ) );

	bb_error( _bl_pushnil( p_lua ) );
	while ( 1 )
	{
		_bl_backupstack( p_lua, &n_etop );
		if ( 0 == lua_next( p_lua->p_state, n_index ) )
			break;
		lua_pushvalue( p_lua->p_state, -2 );
		lua_pushvalue( p_lua->p_state, -2 );
		lua_remove( p_lua->p_state, -3 );
		pfn_onenum( p_lua );
		_bl_recoverystack( p_lua, n_etop );

		bb_error( _bl_istable( p_lua, n_index ) );
	}

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

static int _bl_isnumber( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isnumber( p_lua->p_state, n_index );	

	bb_exit
	return b_ret;
}

static int _bl_isstring( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isstring( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isboolean( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isboolean( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isfunction( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isfunction( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_iscfunction( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_iscfunction( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_islightuserdata( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_islightuserdata( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isuserdata( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isuserdata( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_istable( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_istable( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isthread( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isthread( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isnil( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isnil( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isnone( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isnone( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_isnoneornil( pblua_t p_lua, int n_index )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	b_ret = lua_isnoneornil( p_lua->p_state, n_index );

	bb_exit
	return b_ret;
}

static int _bl_toint( pblua_t p_lua, int n_index, int* pn_value )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state && pn_value );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	*pn_value = (int)lua_tointeger( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return 1;
}

static int _bl_tostr( pblua_t p_lua, int n_index, char* psz_buffer, size_t* pn_len )
{
	int b_ret = 0;
	const char* psz_value;
	size_t un_valuelen = 0;

	bb_assert( p_lua && p_lua->p_state && pn_len );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	bb_error( psz_value = lua_tolstring( p_lua->p_state, n_index, &un_valuelen ) );
	if ( psz_buffer )
	{
		if ( *pn_len < un_valuelen + 1 )
		{
			bb_error( 0 && "buffer len is too short" );
		}
		strcpy( psz_buffer, psz_value );
	}

	b_ret  = 1;
	bb_exit
	*pn_len = un_valuelen;
	return b_ret;
}

static int _bl_tobool( pblua_t p_lua, int n_index, int* pn_value )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state && pn_value );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	*pn_value = lua_toboolean( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_tocfunc( pblua_t p_lua, int n_index, lua_cfunc* ppfn_value )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state && ppfn_value );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	*ppfn_value = lua_tocfunction( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return b_ret;
}
static int _bl_topointer( pblua_t p_lua, int n_index, blua_pointer* pbp_value )
{
	int b_ret = 0;

	bb_assert( p_lua && p_lua->p_state && pbp_value );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	*pbp_value = lua_topointer( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_tonumber( pblua_t p_lua, int n_index, blua_number* pd_value )
{
	int b_ret = 0;

	bb_assert( p_lua->p_state && pd_value );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	*pd_value = lua_tonumber( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_touserdata( pblua_t p_lua, int n_index, void** pp_value )
{
	int b_ret = 0;

	bb_assert( p_lua->p_state && pp_value );
	bb_error( -1 != _bl_transindex( p_lua, n_index ) );
	*pp_value = lua_touserdata( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_backupstack( pblua_t p_lua, int* pn_top )
{
	bb_assert( p_lua && p_lua->p_state && pn_top );
	*pn_top = lua_gettop( p_lua->p_state );
	return 1;
}

static int _bl_recoverystack( pblua_t p_lua, int n_top )
{
	bb_assert( p_lua && p_lua->p_state );
	lua_settop( p_lua->p_state, n_top );
	return 1;
}

static int _bl_getfieldbyname( pblua_t p_lua, const char* psz_fieldname )
{
	__________(head)____________
	int b_ret = 0;
	int n_otop = 0, n_ntop1 = 0, n_ntop2 = 0;
	int n_level = 0;
	int n_index = LUA_GLOBALSINDEX;
	char ca_name[256] = { 0 };
	size_t n_fieldlen = 0;
	char* pc_one = NULL;
	char* pc_sec = NULL;

	___________(body)____________
	bb_assert( p_lua && p_lua->p_state && psz_fieldname );

	n_fieldlen = strlen( psz_fieldname ) + 1;
	bb_error( n_fieldlen <= 256 && "invalid field name:longer than 256" );
	strcpy( ca_name, psz_fieldname );

	n_otop = lua_gettop( p_lua->p_state );
	pc_one = ca_name;
	while( 1 )
	{
		size_t n_fieldlen = 0;

		bb_error( lua_istable( p_lua->p_state, n_index ) && "invalid field name:type table expected" );
		bb_error( n_level <= 16 && "invalid field name:level larger than 16" );

		pc_sec = strchr( pc_one, '.' );
		if ( pc_sec )
		{
			n_fieldlen = pc_sec - pc_one;
			*pc_sec = 0;
		}
		else
		{
			n_fieldlen = strlen( pc_one );
		}
		bb_error( n_fieldlen && "invalid field name:blank field" );

		n_ntop1 = lua_gettop( p_lua->p_state );
		lua_getfield( p_lua->p_state, n_index, pc_one );
		n_ntop2 = lua_gettop( p_lua->p_state );
		bb_error( n_ntop2 > n_ntop1 && "invalid field name:not exist field name" );

		n_index = -1;
		n_level++;
		if ( !pc_sec )
			break;

		pc_one = pc_sec + 1;
		pc_sec = NULL;
	}
	//恢復堆棧,并把得到的最終結果push到初始堆棧上面,正確返回時,堆棧上元素個數比函數調用前多一，失敗返回時，則保持不變
	bb_assert( n_ntop2 > n_otop && "invalid stack operation" );
	if ( n_ntop2 > n_otop + 1 )
	{
		lua_replace( p_lua->p_state, n_otop + 1 );
		lua_settop( p_lua->p_state, n_otop + 1 );
	}

	___________(end)____________
	b_ret = 1;
	bb_exit
	if ( !b_ret )
	{
		lua_settop( p_lua->p_state, n_otop );
	}
	return b_ret;
}

static int _bl_setfieldbyname( pblua_t p_lua, const char* pszu8_fieldname, int* pn_tableindex )
{
	int b_ret = 0;
	char* pc_one = NULL;
	char* pc_sec = NULL;
	char ca_field[BLD_MAX_FIELD_LEN];
	size_t un_fieldlen = 0;
	size_t un_level = 0;
	int n_index = LUA_GLOBALSINDEX;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state && pszu8_fieldname && pn_tableindex );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );

	un_fieldlen = strlen( pszu8_fieldname ) + 1;
	bb_error( un_fieldlen <= BLD_MAX_FIELD_LEN && "setfieldbyname error:field name too long" );
	strcpy( ca_field, pszu8_fieldname );

	pc_one = ca_field;
	while ( 1 )
	{
		size_t un_onefieldlen = 0;

		bb_error( lua_istable( p_lua->p_state, n_index ) && "setfieldbyname error:table expected" );
		bb_error( un_level <= BLD_MAX_FIELD_LEVEL && "setfieldbyname error:field level too large" );

		pc_sec = strchr( pc_one, '.' );
		if ( pc_sec )
		{
			un_onefieldlen = pc_sec - pc_one;
			*pc_sec = 0;
		}
		else
		{
			un_onefieldlen = strlen( pc_one );
		}
		bb_error( un_onefieldlen > 0 && "setfielddbyname error:blank field name" );

		if ( pc_sec )
		{
			bb_error( _bl_pushstring( p_lua, pc_one ) );
			bb_error( _bl_gettable( p_lua, n_index ) );
			if ( !lua_istable( p_lua->p_state, -1 ) )
			{
				_bl_pop( p_lua, 1 );
				bb_error( _bl_pushstring( p_lua, pc_one ) );
				bb_error( _bl_pushtable( p_lua ) );
				bb_error( _bl_settable( p_lua, n_index ) );

				bb_error( _bl_pushstring( p_lua, pc_one ) );
				bb_error( _bl_gettable( p_lua, n_index ) );
			}
			n_index = _bl_transindex( p_lua, -1 );
			//保持堆棧。
			if ( n_index > n_otop + 1 )
			{
				lua_replace( p_lua->p_state, n_otop + 1 );
				lua_settop( p_lua->p_state, n_otop + 1 );
			}
			n_index = _bl_transindex( p_lua, -1 );
		}
		else
		{
			bb_error( _bl_pushstring( p_lua, pc_one ) );
		}

		un_level++;
		if ( !pc_sec )
			break;

		pc_one = pc_sec + 1;
		pc_sec = NULL;
	}

	*pn_tableindex = n_index;
	b_ret = 1;
	bb_exit
	if ( !b_ret )
	{
		_bl_recoverystack( p_lua, n_otop );
	}
	return b_ret;
}

static int _bl_pop( pblua_t p_lua, int n_cnt )
{
	bb_assert( p_lua && p_lua->p_state );
	lua_pop( p_lua->p_state, n_cnt );
	return 1;
}

static int _bl_insert( pblua_t p_lua, int n_index )
{
	int b_ret = 0;
	int n_otop = 0;

	bb_assert( p_lua && p_lua->p_state );

	bb_error( -1 != ( n_index = _bl_transindex( p_lua, n_index ) ) );
	bb_error( n_index != 0 );
	lua_insert( p_lua->p_state, n_index );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_pushnil( pblua_t p_lua )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );
	n_otop = lua_gettop( p_lua->p_state );
	lua_pushnil( p_lua->p_state );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 && "push nil error" );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_pushint( pblua_t p_lua, int n_value )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );
	n_otop = lua_gettop( p_lua->p_state );
	lua_pushinteger( p_lua->p_state, n_value );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 && "push interger error" );

	b_ret = 1;
	bb_exit
	return b_ret;
}
static int _bl_pushstring( pblua_t p_lua, const char* psz_value )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state && psz_value );
	n_otop = lua_gettop( p_lua->p_state );
	lua_pushstring( p_lua->p_state, psz_value );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_pushlightpointer( pblua_t p_lua, void* p_pointer )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );
	n_otop = lua_gettop( p_lua->p_state );
	lua_pushlightuserdata( p_lua->p_state, p_pointer );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_pushvalue( pblua_t p_lua, int n_index )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );

	n_otop = lua_gettop( p_lua->p_state );
	lua_pushvalue( p_lua->p_state, n_index );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_pushtable( pblua_t p_lua )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state );

	n_otop = lua_gettop( p_lua->p_state );
	lua_newtable( p_lua->p_state );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_pushcclosure( pblua_t p_lua, lua_cfunc pfn_func, int n_upvcnt )
{
	int b_ret = 0;
	int n_otop = 0, n_ntop = 0;

	bb_assert( p_lua && p_lua->p_state && pfn_func && n_upvcnt >= 0 && n_upvcnt < 255 );

	n_otop = lua_gettop( p_lua->p_state );
	bb_error( n_otop >= n_upvcnt );
	lua_pushcclosure( p_lua->p_state, pfn_func, n_upvcnt );
	n_ntop = lua_gettop( p_lua->p_state );
	bb_error( n_ntop == n_otop + 1 - n_upvcnt );

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_exportlib( pblua_t p_lua, const char* pszu8_tablename, pluareg_t p_regs, int n_upvcnt )
{
	int b_ret = 0;
	int n_tableindex = 0;
	int n_otop = 0;

	bb_assert( p_lua && p_lua->p_state && pszu8_tablename && p_regs && n_upvcnt >= 0 && n_upvcnt < 255 );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_tablename, &n_tableindex ) );
	bb_error( _bl_pushtable( p_lua ) );
	bb_error( _bl_insert( p_lua, -2 ) );
	bb_error( _bl_pushvalue( p_lua, -2 ) );
	bb_error( _bl_settable( p_lua, n_tableindex ) );

	while( NULL != p_regs->pszu8_funcname && NULL != p_regs->pfn_func )
	{
		bb_error( _bl_pushstring( p_lua, p_regs->pszu8_funcname ) );
		bb_error( _bl_pushcclosure( p_lua, p_regs->pfn_func, 0 ) );
		bb_error( _bl_settable( p_lua, -3 ) );
		p_regs++;
	}

	b_ret = 1;
	bb_exit
	_bl_recoverystack( p_lua, n_otop );
	return b_ret;
}

static int _bl_exportblib( pblua_t p_lua, const char* pszu8_tablename, pbluareg_t p_regs, int n_upvcnt )
{
	int b_ret = 0;
	int n_otop = 0;
	int n_tableindex = 0;

	bb_assert( p_lua && pszu8_tablename && pszu8_tablename && p_regs && n_upvcnt >= 0 && n_upvcnt < 254 );

	bb_error( _bl_backupstack( p_lua, &n_otop ) );
	bb_error( _bl_setfieldbyname( p_lua, pszu8_tablename, &n_tableindex ) );
	bb_error( _bl_pushtable( p_lua ) );
	bb_error( _bl_insert( p_lua, -2 ) );
	bb_error( _bl_pushvalue( p_lua, -2 ) );
	bb_error( _bl_settable( p_lua, n_tableindex ) );

	while( NULL != p_regs->pszu8_funcname && NULL != p_regs->pfn_bfunc )
	{
		bb_error( _bl_pushstring( p_lua, p_regs->pszu8_funcname ) );
		bb_error( _bl_pushlightpointer( p_lua, p_regs->pfn_bfunc ) );
		bb_error( _bl_pushcclosure( p_lua, &_bl_dispatcher, 1 ) );
		bb_error( _bl_settable( p_lua, -3 ) );
		p_regs++;
	}

	b_ret = 1;
	bb_exit
	return b_ret;
}

static int _bl_transindex( pblua_t p_lua, int n_index )
{
	int n_transindex = 0;
	int n_top = 0;

	bb_assert( p_lua && p_lua->p_state );
	
	n_top = lua_gettop( p_lua->p_state );
	n_transindex = n_index;
	if ( LUA_GLOBALSINDEX != n_transindex && n_transindex < 0 )
	{
		n_transindex = n_top + n_index + 1;
		n_transindex = n_transindex < 0 || n_transindex > n_top ? -1 : n_transindex;
	}

	return n_transindex;
}

static int _bl_dispatcher( lua_State* p_state )
{
	pblua_t p_lua = NULL;
	blua_cfunc pfn_bfunc = NULL;
	int n_bfuncret = 0;

	lua_getallocf( p_state, (void**)&p_lua );
	bb_assert( p_lua && p_lua->p_state );
	bb_error( pfn_bfunc = (blua_cfunc)lua_topointer( p_lua->p_state, lua_upvalueindex(1) ) );

	n_bfuncret = pfn_bfunc( p_lua );

	bb_exit
	return n_bfuncret;
}

/***********************************

2010/11/26-14:58 @ corp.king
blua.c
bey0ndc00de
utf-8 --with-sig

************************************/
/*last for linux*/
